#include <QHash>
#include <QRemoteObjectNode>
#include <QEventLoop>

#include "../QRemoteObject2Meta_P.h"
#include "../QRO_p.h"
#include "../QRONode.h"

#include <rep_RemoteInterface_replica.h>


struct ObjectData{
    ObjectID id;
    QList<ObjectID> registerList;//仅头节点该数组有值，当创建头节点时，按照注册顺序将子节点一一放入到该列表中
    QObject* obj;
    QList<QMetaObject::Connection> connections;
};
typedef std::shared_ptr<ObjectData> ObjectDataPtr;
typedef QHash<ObjectID,ObjectDataPtr> ObjectDataMap;

struct QRONode::Private{

    Private(QRONode* P);
    ~Private();

    //对象列表
    ObjectDataMap m_objectDataMap;

    //对象id列表
    QHash<QObject*,ObjectID> m_objectIdMap;

    //远端id与本地id的关联表
    QHash<ObjectID,ObjectID> m_remoteIdMapper;

    RemoteRegistryReplica* m_register;
    RemoteInterfaceReplica* m_channel;
    QRemoteObjectNode* m_node;

    ObjectID lastOwned = NullID;

    ObjectID objectIdGen = 0;

    ObjectID allocObjectID()
    {
        objectIdGen++;
        return objectIdGen;
    }

    InvokeID invokeIdGen = 0;

    InvokeID allocInvokeID()
    {
        invokeIdGen++;
        return invokeIdGen;
    }

    QHash<InvokeID,QRemoteObject2::InvokeCallBack> callBackQueue;

    QRONode* _Q;

    //前端接口
    void onConnectToHost(QString host,QVariant var);
    void onUnregisterObject(QObject* obj);
    void onActiveMethod(QObject* target,int method,QVariantList param,QRemoteObject2::InvokeCallBack callBack);
    void onPushProperty(QObject* target,int prop,QVariant value);
    void onPushParent(QObject* target,QObject* parent);
    void onOccupyObject(QObject* target);
    void onReleaseObject(QObject* target);
    QObject* getOccupiedObject();

    //对象接口
    void handleObjPacket(QVariant value,QList<QObject*>& created);
    //属性接口
    void handleParentPacket(QVariant value);
    //树状图接口
    void handlePropPacket(QVariant value);
    //转换接口
    void valueFromNet(QVariant& param,int targetType);
    void valueToNet(QVariant& param);
    //注册接口
    void unregisterChannel();
    //权限接口
    //调查某个对象（远程id）是否属于本客户端
    /*
    *由于每个客户端只能知道自己已经占领的对象，对象树信息量也只会比服务端少。
    *所以客户端无法精确判断一个对象是否真的属于自己。只能确定出某个对象确实不属于自己
    */
    bool notBelongTo(ObjectID localId);

    //网络接口
    void onNewObject(QByteArray data);
    void onClientCall(int id, int method, QVariantList param,int sync,bool isSource);
    void onPropertyUpdate(QByteArray data);
    void onParentUpdate(int target,int parent);
    void onHostObjectRemoved(QList<quint32> list);
    void onServerCallFinished(int sync,QVariant res,bool success);
    void onOwnedObjectChanged();
};
